#include "graphics/texture.h"

namespace dw
{ 
	namespace graphics
	{	
		ITexture::ITexture(const Type& type, 
			const PixelFormat& pixelFormat, 
			const unsigned width, 
			const unsigned height,
			const Usage& usage) :
			IPixelBuffer(pixelFormat, width, height, usage), 
			_type(type),
			_compressed(false)
		{
		}

		void ITexture::load(std::istream& is)
		{
			//char* filename;
			char* imageData;
			uint32 imageDataSize;
			uint32 numFaces;
			
			ILint ilFormat, ilDataType, ilCubeFlag; 
			ILuint ilDXTCFormat;

			is.seekg(0, std::ios::end);
			imageDataSize = is.tellg();
			is.seekg(0, std::ios::beg);
			imageData = new char[imageDataSize];
			is.read(imageData, imageDataSize);

			ilGenImages(1, &_id);
			ilBindImage(_id);
			ilSetInteger(IL_KEEP_DXTC_DATA, IL_TRUE);
			if (!ilLoadL(IL_TYPE_UNKNOWN, imageData, imageDataSize))
			{
				// DW_ERROR << "Could not open " << _name.c_str() << std::endl;

				ilDeleteImages(1, &_id);
			}
			
			ilCubeFlag		= ilGetInteger(IL_IMAGE_CUBEFLAGS);
			ilFormat			= ilGetInteger(IL_IMAGE_FORMAT);
			ilDataType		= ilGetInteger(IL_IMAGE_TYPE);
			ilDXTCFormat	= ilGetInteger(IL_DXTC_DATA_FORMAT);

			_width			= ilGetInteger(IL_IMAGE_WIDTH);
			_height			= ilGetInteger(IL_IMAGE_HEIGHT);
			_depth			=	ilGetInteger(IL_IMAGE_DEPTH);
			_bpp				= ilGetInteger(IL_IMAGE_BITS_PER_PIXEL);
			_numMipMaps	= ilGetInteger(IL_NUM_MIPMAPS);
			_type				= ilCubeFlag ? TEXTURE_CUBE_MAP : (_height == 1) ? TEXTURE_1D : (_depth == 1) ? TEXTURE_2D : TEXTURE_3D;
			numFaces		= ilCubeFlag ? 6 : 1;

			switch (ilFormat)
			{
				case IL_COLOUR_INDEX	: _pixelFormat = _internalFormat = PF_INDEX			; break ;
				case IL_LUMINANCE			: _pixelFormat = _internalFormat = PF_LUMINANCE	; break ;
				case IL_RGB						: _pixelFormat = _internalFormat = PF_RGB				; break ;
				case IL_RGBA					: _pixelFormat = _internalFormat = PF_RGBA			; break ;
				case IL_BGR						: _pixelFormat = _internalFormat = PF_BGR				; break ;
				case IL_BGRA					: _pixelFormat = _internalFormat = PF_BGRA			; break ;
			}

			for (unsigned mipmap = 0; mipmap < (_numMipMaps + 1); ++mipmap)
			{
				ilActiveMipmap(mipmap);

				if (ilDXTCFormat != IL_DXT_NO_COMP)
				{
					char* dxtcData;

					switch (ilDXTCFormat)
					{
						case IL_DXT1					: _internalFormat = PF_DXT1; break ;
						case IL_DXT2					: _internalFormat = PF_DXT2; break ;
						case IL_DXT3					: _internalFormat = PF_DXT3; break ;
						case IL_DXT4					: _internalFormat = PF_DXT4; break ;
						case IL_DXT5					: _internalFormat = PF_DXT5; break ;
					}

					_compressed = true;
					ILuint ilDXTCSize = ilGetDXTCData(NULL, 0, ilDXTCFormat);
					dxtcData = new char[ilDXTCSize];
					ilGetDXTCData(dxtcData, ilDXTCSize, ilDXTCFormat);
					resize(mipmap, ilDXTCSize);

					unsigned ilDXTCFaceSize = ilDXTCSize / numFaces;
					for (unsigned i = 0; i < numFaces; ++i)
					{
						unsigned offset = i * ilDXTCFaceSize;
						lock(0, 0, IBuffer::BA_WRITE_ONLY);
						write(mipmap, offset, ilDXTCFaceSize, dxtcData);
						unlock();
					}
					
					delete[] dxtcData;
				}
				else
				{
					_compressed = false;
					ILuint ilImageSize = ilGetInteger(IL_IMAGE_SIZE_OF_DATA);
					resize(mipmap, ilImageSize);
					lock(0, 0, IBuffer::BA_WRITE_ONLY);
					write(0, 0, ilImageSize, ilGetData());
					unlock();
				}
			}
			ilDeleteImages(1, &_id);
		}

	} // namespace graphics
} // namespace dw
